/*
 * Copyright (C) 2011 Michael Widmer <widmm8@bfh.ch>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package ch.bfh.aeneas.utils.export;


import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.util.Xml;
import ch.bfh.aeneas.R;
import ch.bfh.aeneas.exchange.data.Node;
import ch.bfh.aeneas.exchange.data.Route;
import ch.bfh.aeneas.exchange.data.NoItemFoundException;
import ch.bfh.aeneas.exchange.intent.AeneasIntent;
import ch.bfh.aeneas.navigation.app.NavigationActivity;
import ch.bfh.aeneas.provider.storage.db.DBOpenHelper;
import ch.bfh.aeneas.provider.storage.db.DatabaseService;
import ch.bfh.aeneas.provider.storage.db.DatabaseService.DatabaseBinder;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import org.xmlpull.v1.XmlSerializer;



/**
 *
 * @author Michael Widmer <widmm8@bfh.ch>
 */
public class ExportMe extends Activity {

    protected ServiceConnection mDataConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName arg0, IBinder arg1) {
            mDataManager = (DatabaseService) ((DatabaseBinder) arg1).getService();
            
            DBOpenHelper dbo = new DBOpenHelper(mDataManager);
            mDb = dbo.getReadableDatabase();
            
            onDataReady();
        }

        public void onServiceDisconnected(ComponentName arg0) {
        }        
    };
    
    private DatabaseService mDataManager;
    private SQLiteDatabase mDb;
    private final String LOG_TAG = "Exporter";
    protected List<Route> mRoutes;
    protected List<Node> mNodes;
    private boolean mOutputKml;
    private Resources res;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        res=getResources();
        
        Log.i(LOG_TAG, "In onCreate of Exporter!");
        
        mRoutes = new ArrayList<Route>();
        mNodes = new ArrayList<Node>();
        
        Intent start = getIntent();
        if(start.hasExtra("kml")) {
            mOutputKml = start.getBooleanExtra("kml", false);
        }
        
        Intent i = new Intent(this, DatabaseService.class);
        bindService(i, mDataConnection, Activity.BIND_AUTO_CREATE);
    }
    
    protected void onDataReady() {
        Log.i(LOG_TAG, "onDataReady");
        
        Cursor c = mDb.rawQuery("SELECT route_id FROM routes", null);
        c.moveToFirst();
        if(c.getCount() > 0) {
            Log.i(LOG_TAG, "Found "+c.getCount()+" routes!");
            parseRoutes(c);
        } else {
            Log.i(LOG_TAG, "Sorry! No routes found!");
        }
        c.close();
        
        c = mDb.rawQuery("SELECT node_id FROM nodes", null);
        c.moveToFirst();
        if(c.getCount() > 0) {
            Log.i(LOG_TAG, "Found "+c.getCount()+" nodes!");
            parseNodes(c);
        } else {
            Log.i(LOG_TAG, "Sorry! No nodes found!");
        }
        c.close();
        
        if(mOutputKml) {
            writeKmlFile();
        } else {
            writeXmlFile();
        }
        
        Intent output = new Intent(AeneasIntent.ACTION_OUTPUT);
        output.putExtra("speech", res.getString(R.string.export_successful));
        output.putExtra("useAi", false);
        super.sendBroadcast(output);
        
        finish();
    }
    
    @Override
    public void onDestroy() {
        mDb.close();
        
        unbindService(mDataConnection);
        super.onDestroy();
    }
    
    protected void parseRoutes(Cursor c) {
        c.moveToFirst();
        int cId;
        int rId;
        while(!c.isAfterLast()) {
            cId = c.getColumnIndex("route_id");
            rId = c.getInt(cId);
            try {
                mRoutes.add(mDataManager.getRouteById(rId));
            } catch (NoItemFoundException ex) {
                Log.w(LOG_TAG, "No route found for id "+rId);
            }
            c.moveToNext();
        }
    }
    
    protected void parseNodes(Cursor c) {
        c.moveToFirst();
        int cId;
        int nId;
        while(!c.isAfterLast()) {
            cId = c.getColumnIndex("node_id");
            nId = c.getInt(cId);
            try {
                mNodes.add(mDataManager.getNodeById(nId));
            } catch (NoItemFoundException ex) {
                Log.w(LOG_TAG, "No node found for id "+nId);
            }
            c.moveToNext();
        }
    }

    private void writeKmlFile() {
        Route r;
        Node n;
        String writtenFile;
        XmlSerializer serializer = Xml.newSerializer();
        //serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", "    ");
        //serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\r\n");
        StringWriter writer = new StringWriter();
        try {
            serializer.setOutput(writer);
            serializer.startDocument("UTF-8", true);
            serializer.startTag("", "kml");
            serializer.attribute("", "xmlns", "http://www.opengis.net/kml/2.2");
            serializer.text("\r\n");
            
            serializer.startTag("","Document");
            serializer.text("\r\n");
            
                serializer.startTag("", "name");
                serializer.text(getString(R.string.export_name_paths));
                serializer.endTag("", "name");
                serializer.text("\r\n");
                
                serializer.startTag("", "description");
                serializer.text("");
                serializer.endTag("", "description");
                serializer.text("\r\n");
                
                serializer.startTag("","Style");
                serializer.attribute("", "id", "yellowLineGreenPoly");
                serializer.text("\r\n");
                
                    serializer.startTag("", "LineStyle");
                    serializer.text("\r\n");
                    
                        serializer.startTag("", "color");
                        serializer.text("7f00ffff");
                        serializer.endTag("", "color");
                        serializer.text("\r\n");
                    
                    serializer.endTag("", "LineStyle");
                    serializer.text("\r\n");
                
                    serializer.startTag("", "PolyStyle");
                    serializer.text("\r\n");
                    
                        serializer.startTag("", "color");
                        serializer.text("7f00ffff");
                        serializer.endTag("", "color");
                        serializer.text("\r\n");
                    
                    serializer.endTag("", "PolyStyle");
                    serializer.text("\r\n");
                    
                serializer.endTag("","Style");
                serializer.text("\r\n");
                
                for(int i = 0; i < mRoutes.size(); i++) {
                    r = mRoutes.get(i);
                    writeKmlRoute(serializer, r);
                }
                
                
            serializer.endTag("", "Document");
            serializer.text("\r\n");
            serializer.endDocument();
            
            writtenFile = writer.toString();
            
            try {
                File root = Environment.getExternalStorageDirectory();
                if (root.canWrite()){
                    String ending = mOutputKml?"kml":"xml";
                    File gpxfile = new File(root, "aeneas/dbexport."+ending);
                    FileWriter gpxwriter = new FileWriter(gpxfile);
                    BufferedWriter out = new BufferedWriter(gpxwriter);
                    out.write(writtenFile);
                    out.close();
                } else {
                    Log.i(LOG_TAG, "Sorry! No rights for writing file on SD-Card! :(");
                }
            } catch (IOException e) {
                Log.e("Exporter", "Could not write file " + e.getMessage());
            }
        } catch (Exception e) {
            Log.e("Exporter", "Could not parse data: " + e.getMessage());
        } 
    }
    
    private void writeXmlFile() {
        
        Route r;
        Node n;
        String writtenFile;
        XmlSerializer serializer = Xml.newSerializer();
        //serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", "    ");
        //serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\r\n");
        StringWriter writer = new StringWriter();
        try {
            serializer.setOutput(writer);
            serializer.startDocument("UTF-8", true);
            serializer.startTag("", "database");
            serializer.text("\r\n");
            serializer.startTag("","routes");
            serializer.text("\r\n");
            for(int i = 0; i < mRoutes.size(); i++) {
                r = mRoutes.get(i);
                writeXmlRoute(serializer, r);
                //serializer.text("\r\n");
            }
            serializer.endTag("", "routes");
            serializer.text("\r\n");
            serializer.startTag("","nodes");
            serializer.text("\r\n");
            for(int i = 0; i < mNodes.size(); i++) {
                n = mNodes.get(i);
                writeXmlNode(serializer, n);
                //serializer.text("\r\n");
            }
            serializer.endTag("", "nodes");
            serializer.text("\r\n");
            serializer.endTag("", "database");
            serializer.text("\r\n");
            serializer.endDocument();
            
            writtenFile = writer.toString();
            
            try {
                File root = Environment.getExternalStorageDirectory();
                if (root.canWrite()){
                    File gpxfile = new File(root, "aeneas/dbexport.xml");
                    FileWriter gpxwriter = new FileWriter(gpxfile);
                    BufferedWriter out = new BufferedWriter(gpxwriter);
                    out.write(writtenFile);
                    out.close();
                } else {
                    Log.i(LOG_TAG, "Sorry! No rights for writing file on SD-Card! :(");
                }
            } catch (IOException e) {
                Log.e("Exporter", "Could not write file " + e.getMessage());
            }
        } catch (Exception e) {
            Log.e("Exporter", "Could not parse data: " + e.getMessage());
        } 
    }

    private void writeXmlRoute(XmlSerializer serializer, Route r) throws IllegalStateException, IOException, IllegalArgumentException {
        serializer.startTag("","route");
        
        serializer.attribute("", "name",r.getName());
        serializer.attribute("", "date",r.getDate().toGMTString());
        serializer.attribute("", "collection",r.isGroup()?"true":"false");
        serializer.text("\r\n");
        
        serializer.startTag("", "nodes");
        serializer.text("\r\n");
        
        Node n;
        List<Node> nodes = r.getNodes();
        for(int i = 0; i < nodes.size(); i++) {
            n = nodes.get(i);
            writeXmlNode(serializer, n);
        }
        
        serializer.endTag("", "nodes");
        serializer.text("\r\n");
        serializer.endTag("","route");
        serializer.text("\r\n");
    }

    private void writeKmlRoute(XmlSerializer serializer, Route r) throws IllegalStateException, IOException, IllegalArgumentException {
        serializer.startTag("", "Placemark");
        serializer.text("\r\n");
        
            serializer.startTag("", "name");
            serializer.text(r.getName());
            serializer.endTag("", "name");
            serializer.text("\r\n");
            
            serializer.startTag("", "description");
            serializer.text("RecordingDate: "+r.getDate().toGMTString());
            serializer.endTag("", "description");
            serializer.text("\r\n");
        
            serializer.startTag("", "styleUrl");
            serializer.text("#yellowLineGreenPoly");
            serializer.endTag("", "styleUrl");
            serializer.text("\r\n");
        
            serializer.startTag("", "LineString");
            serializer.text("\r\n");
                
                serializer.startTag("", "extrude");
                serializer.text("1");
                serializer.endTag("", "extrude");
                serializer.text("\r\n");
            
                serializer.startTag("", "tessellate");
                serializer.text("1");
                serializer.endTag("", "tessellate");
                serializer.text("\r\n");
                
                serializer.startTag("", "altitudeMode");
                serializer.text("absolute");
                serializer.endTag("", "altitudeMode");
                serializer.text("\r\n");
                
                serializer.startTag("", "coordinates");
                Node n;
                List<Node> nodes = r.getNodes();
                for(int i = 0; i < nodes.size(); i++) {
                    n = nodes.get(i);
                    serializer.text(n.getLongitude()+","+n.getLatitude()+","+n.getAltitude());
                    serializer.text("\r\n");
                }
                serializer.endTag("", "coordinates");
                serializer.text("\r\n");
                
            serializer.endTag("", "LineString");
            serializer.text("\r\n");
            
        serializer.endTag("", "Placemark");
        serializer.text("\r\n");
    }

    private void writeXmlNode(XmlSerializer serializer, Node n) throws IllegalStateException, IOException, IllegalArgumentException {
        serializer.startTag("","node");
        
        String address = n.getAddress();
        String name = n.getName();
        
        if(name != null && name.equalsIgnoreCase(""))
            serializer.attribute("", "name", name);
        if(address != null && address.equalsIgnoreCase(""))
            serializer.attribute("", "address", address);
        serializer.text("\r\n");
        
        serializer.startTag("", "lat");
        serializer.text(Double.toString(n.getLatitude()));
        serializer.endTag("", "lat");
        serializer.text("\r\n");
        
        serializer.startTag("", "lng");
        serializer.text(Double.toString(n.getLongitude()));
        serializer.endTag("", "lng");
        serializer.text("\r\n");
        
        serializer.endTag("","node");
        serializer.text("\r\n");
    }
}